from django.shortcuts import render, redirect, HttpResponse, reverse
from django.http.response import JsonResponse
from web import models
from utils.tencent.cos import delete_bucket
from web.Forms.issues import IssuesModelForm, IssuesReplyModelForm, InviteModelForm
from utils.pagination import Pagination
from django.views.decorators.csrf import csrf_exempt
import json
from django.utils.safestring import mark_safe
from utils.encrypt import uid
import datetime

'''问题'''


class CheckFilter():
    def __init__(self, name, data_list, request):
        self.name = name
        self.data_list = data_list
        self.request = request

    def __iter__(self):
        for item in self.data_list:
            key = str(item[0])
            text = item[1]
            value_list = self.request.GET.getlist(self.name)
            ck = ""
            if key in value_list:
                ck = "checked"
                value_list.remove(key)
            else:
                value_list.append(key)

            query_dict = self.request.GET.copy()  # 得到后面得?status=1&status=2
            query_dict._mutable = True  # 允许修改
            query_dict.setlist(self.name, value_list)  # 设置 {'status':[1,2]} 在原有得基础上加 原来有的已经删除了
            if 'page' in query_dict:
                query_dict.pop('page')
            param_url = query_dict.urlencode()
            if param_url:
                url = '{}?{}'.format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1
            else:
                url = self.request.path_info
            tpl = f'<a class="cell" href="{url}"><input type="checkbox" {ck} /><label>{text}</label></a>'
            html = tpl.format(url=url, ck=ck, text=text)
            yield mark_safe(html)


class SelectFilter(object):
    def __init__(self, name, data_list, request):
        self.name = name
        self.data_list = data_list
        self.request = request

    def __iter__(self):
        yield mark_safe("<select class='select2' multiple='multiple' style='width:100%;' >")
        for item in self.data_list:
            key = str(item[0])
            text = item[1]

            selected = ""
            value_list = self.request.GET.getlist(self.name)
            if key in value_list:
                selected = 'selected'
                value_list.remove(key)
            else:
                value_list.append(key)

            query_dict = self.request.GET.copy()
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)
            if 'page' in query_dict:
                query_dict.pop('page')

            param_url = query_dict.urlencode()
            if param_url:
                url = "{}?{}".format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1
            else:
                url = self.request.path_info

            html = "<option value='{url}' {selected} >{text}</option>".format(url=url, selected=selected, text=text)
            yield mark_safe(html)
        yield mark_safe("</select>")


def issues(request, project_id):
    """问题"""
    dic = {
        'status': 1,
        'msg': ''
    }
    # 基础url搜索
    if request.method == 'GET':
        allow_filter_name = ['issues_type', 'status', 'priority', 'assign', 'attention']
        condition = {}
        for name in allow_filter_name:
            value_list = request.GET.getlist(name)  # [1,]
            if not value_list:
                continue
            condition['{}__in'.format(name)] = value_list
            """
            构建成双下滑线
                condition = {
                    "status__in":[1,2],
                    'issues_type__in':[1,]
                }
            """

        form = IssuesModelForm(request)
        # 分页器
        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)
        page_object = Pagination(current_page=request.GET.get('page'),
                                 all_count=queryset.count(),
                                 base_url=request.path_info,
                                 query_params=request.GET,
                                 per_page=10
                                 )
        invite_form = InviteModelForm()
        issues_object_list = queryset[page_object.start:page_object.end]
        page_html = page_object.page_html()
        project_issues_type = models.IssuesType.objects.filter(project_id=project_id).values_list('id', 'title')
        project_total_user = [(request.tracer.project.id, request.tracer.project.creator.username)]
        join_user = models.ProjectUser.objects.filter(project_id=project_id).values_list('user_id', 'user__username')
        project_total_user.extend(join_user)
        # 返回一个对象
        filter_list = [
            {'title': "问题类型", 'filter': CheckFilter('issues_type', project_issues_type, request)},
            {'title': "问题类型", 'filter': CheckFilter('status', models.Issues.status_choices, request)},
            {'title': "优先级", 'filter': CheckFilter('priority', models.Issues.priority_choices, request)},
            {'title': "指派者", 'filter': SelectFilter('assign', project_total_user, request)},
            {'title': "关注者", 'filter': SelectFilter('attention', project_total_user, request)},
        ]
        return render(request, 'issues.html', locals())

    form = IssuesModelForm(request, data=request.POST)
    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()

        return JsonResponse(dic)
    dic['status'] = 0
    dic['msg'] = form.errors
    return JsonResponse(dic)


def issues_detail(request, project_id, issues_id):
    '''编辑'''
    issues_object = models.Issues.objects.filter(project_id=project_id, id=issues_id).first()
    form = IssuesModelForm(request, instance=issues_object)
    return render(request, 'issues_detail.html', locals())


@csrf_exempt
def issues_record(request, project_id, issues_id):
    """ 初始化操作记录 """
    dic = {
        'status': 1,
        'data': '',
        'msg': ''
    }
    if request.method == 'GET':
        # 获取当前所有评论
        reply_list = models.IssuesReply.objects.filter(creator=request.tracer.user, issues__project_id=project_id)
        # 构造字典数据
        data_list = []
        for row in reply_list:
            data = {
                'id': row.id,
                'reply_type_text': row.get_reply_type_display(),
                'content': row.content,
                'creator': row.creator.username,
                'datetime': row.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': row.reply_id
            }
            data_list.append(data)
            dic['data'] = data_list
        return JsonResponse(dic)
    form = IssuesReplyModelForm(data=request.POST)
    if form.is_valid():
        form.instance.issues_id = issues_id
        form.instance.reply_type = 2
        form.instance.creator = request.tracer.user
        instance = form.save()
        info = {
            'id': instance.id,
            'reply_type_text': instance.get_reply_type_display(),
            'content': instance.content,
            'creator': instance.creator.username,
            'datetime': instance.create_datetime.strftime("%Y-%m-%d %H:%M"),
            'parent_id': instance.reply_id
        }
        dic['data'] = info
        return JsonResponse(dic)
    dic['msg'] = form.errors
    dic['status'] = 0
    return JsonResponse(dic)


@csrf_exempt
def issues_change(request, project_id, issues_id):
    issues_object = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    post_dict = json.loads(request.body.decode('utf-8'))
    """
    {'name': 'subject', 'value': '好饿呀sdfasdf'}
    {'name': 'subject', 'value': ''}

    {'name': 'desc', 'value': '好饿呀sdfasdf'}
    {'name': 'desc', 'value': ''}

    {'name': 'start_date', 'value': '好饿呀sdfasdf'}
    {'name': 'end_date', 'value': '好饿呀sdfasdf'}

    {'name': 'issues_type', 'value': '2'}
    {'name': 'assign', 'value': '4'}
    """
    name = post_dict.get('name')
    value = post_dict.get('value')
    # 拿到表字段
    field_object = models.Issues._meta.get_field(name)

    # print(post_dict)
    def create_reply_record(content):
        new_object = models.IssuesReply.objects.create(
            reply_type=1,
            issues=issues_object,
            content=change_record,
            creator=request.tracer.user,
        )
        new_reply_dict = {
            'id': new_object.id,
            'reply_type_text': new_object.get_reply_type_display(),
            'content': new_object.content,
            'creator': new_object.creator.username,
            'datetime': new_object.create_datetime.strftime("%Y-%m-%d %H:%M"),
            'parent_id': new_object.reply_id
        }
        return new_reply_dict

    # 1. 数据库字段更新
    # 1.1 文本
    if name in ["subject", 'desc', 'start_date', 'end_date']:
        if not value:
            if not field_object.null:
                return JsonResponse({'status': False, 'error': "您选择的值不能为空"})
            setattr(issues_object, name, None)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:
            setattr(issues_object, name, value)
            issues_object.save()
            # 记录：xx更为了value
            change_record = "{}更新为{}".format(field_object.verbose_name, value)

        return JsonResponse({'status': True, 'data': create_reply_record(change_record)})

    # 1.2 FK字段（指派的话要判断是否创建者或参与者）
    if name in ['issues_type', 'module', 'parent', 'assign']:
        # 用户选择为空
        if not value:
            # 不允许为空
            if not field_object.null:
                return JsonResponse({'status': False, 'error': "您选择的值不能为空"})
            # 允许为空
            setattr(issues_object, name, None)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:  # 用户输入不为空
            if name == 'assign':
                # 是否是项目创建者
                if value == str(request.tracer.project.creator_id):
                    instance = request.tracer.project.creator
                else:
                    project_user_object = models.ProjectUser.objects.filter(project_id=project_id,
                                                                            user_id=value).first()
                    if project_user_object:
                        instance = project_user_object.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})

                setattr(issues_object, name, instance)
                issues_object.save()
                change_record = "{}更新为{}".format(field_object.verbose_name, str(instance))  # value根据文本获取到内容
            else:
                # 条件判断：用户输入的值，是自己的值。
                instance = field_object.rel.model.objects.filter(id=value, project_id=project_id).first()
                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})

                setattr(issues_object, name, instance)
                issues_object.save()
                change_record = "{}更新为{}".format(field_object.verbose_name, str(instance))  # value根据文本获取到内容

        return JsonResponse({'status': True, 'data': create_reply_record(change_record)})

    # 1.3 choices字段
    if name in ['priority', 'status', 'mode']:
        selected_text = None
        for key, text in field_object.choices:
            if str(key) == value:
                selected_text = text
        if not selected_text:
            return JsonResponse({'status': False, 'error': "您选择的值不存在"})

        setattr(issues_object, name, value)
        issues_object.save()
        change_record = "{}更新为{}".format(field_object.verbose_name, selected_text)
        return JsonResponse({'status': True, 'data': create_reply_record(change_record)})

    # 1.4 M2M字段
    if name == "attention":
        # {"name":"attention","value":[1,2,3]}
        if not isinstance(value, list):
            return JsonResponse({'status': False, 'error': "数据格式错误"})

        if not value:
            issues_object.attention.set(value)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:
            # values=["1","2,3,4]  ->   id是否是项目成员（参与者、创建者）
            # 获取当前项目的所有成员
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.username}
            project_user_list = models.ProjectUser.objects.filter(project_id=project_id)
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username
            username_list = []
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    return JsonResponse({'status': False, 'error': "用户不存在请重新设置"})
                username_list.append(username)

            issues_object.attention.set(value)
            issues_object.save()
            change_record = "{}更新为{}".format(field_object.verbose_name, ",".join(username_list))

        return JsonResponse({'status': True, 'data': create_reply_record(change_record)})

    return JsonResponse({'status': False, 'error': "滚"})


def invite_url(request, project_id):
    """生成邀请码"""
    form = InviteModelForm(data=request.POST)
    if form.is_valid():
        if request.tracer.user != request.tracer.project.creator:
            form.add_error('period', "无权创建邀请码")
            return JsonResponse({'status': False, 'error': form.errors})
        # 保存数据
        random_invite_code = uid(request.tracer.user.mobile_phone)

        form.instance.project = request.tracer.project
        form.instance.code = random_invite_code
        form.instance.creator = request.tracer.user
        form.save()
        # 生成链接
        url = "{scheme}://{host}{invite_join}".format(
            scheme=request.scheme,
            host=request.get_host(),
            invite_join=reverse('invite_join', kwargs={'code': random_invite_code})

        )
        return JsonResponse({'status': True, 'data': url})

    return JsonResponse({'status': False, 'error': form.errors})


def invite_join(request, code):
    """ 访问邀请码 """  # 站在邀请码的角度，及当前拿着邀请码登录的用户的角度
    invite_object = models.ProjectInvite.objects.filter(code=code).first()
    # 1. 邀请码是否存在
    if not invite_object:
        return render(request, 'invite_join.html', {'error': '邀请码不存在'})
    # 2. 邀请的人是否为邀请的项目的创建者
    if request.tracer.user == invite_object.project.creator:
        return render(request, 'invite_join.html', {'error': '项目创建者无需再加入项目'})
    # 3. 邀请的人是否已经参加该项目
    exits = models.ProjectUser.objects.filter(user=request.tracer.user, project=invite_object.project).filter()
    if exits:
        return render(request, 'invite_join.html', {'error': '你已经加入该项目'})

    # current_transact 邀请项目的创建者的价格策略
    current_transact = models.Transact.objects.filter(user=invite_object.project.creator).order_by('-id').first()
    # 价格策略是否为免费的/是否过期了
    # 免费的价格策略
    free_transact = models.PricePolicy.objects.filter(category=1).first()
    if current_transact.price_policy.category == 1 or current_transact.end_datetime < datetime.datetime.now():
        max_number = free_transact.project_member
    else:
        max_number = current_transact.price_policy.project_member
    # 4. 邀请的项目成员额度是否足够
    # 当前项目的所有成员
    total_user = models.ProjectUser.objects.filter(project=invite_object.project).count()
    # 把创建者也1添加进来
    total_user += 1
    if not total_user <= max_number:
        return render(request, 'invite_join.html', {'error': '当前项目成员数量已经满员'})
    # 5. 当前邀请码是否过期
    if invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period) <= datetime.datetime.now():
        return render(request, 'invite_join.html', {'error': '邀请码过期'})
    # 6. 邀请人数是否用完
    invite_number = invite_object.count
    # 有人数限制
    if invite_number:
        # 人数用完了
        if invite_object.use_count >= invite_object.count:
            return render(request, 'invite_join.html', {'error': '邀请名额已经达到上线'})
        else:
            invite_object.use_count += 1
            invite_object.save()

    # 当前登录的对象
    models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)
    # invite_object 的字段更新
    invite_object.project.join_count += 1
    invite_object.save()

    return render(request, 'invite_join.html', {'project': invite_object.project})
